#include "Sistema.h"
#include <iostream>
#include <fstream>

Sistema Sistema::sistema;

Sistema::Sistema(){
     AC1=C1=0;
     terminados=0;
}

Sistema& Sistema::getInstancia(){
     return sistema;
}

void Sistema::start(uint64_t cantidad){
     while(terminados < cantidad){
	  Evento* ev;
	  uint64_t tiempo;
	  /* Obtengo los menores de la FEC y los ejecuto */
	  ev=FEC.front();
	  tiempo = ev->getTiempo();
	  /* Pongo los relojes a esa hora */
	  AC1+=tiempo;
	  C1+=tiempo;
	  do{
	       FEC.pop_front();
	       ev->ejecutar();
	       delete ev;
	       ev=FEC.front();
	  }while(ev->getTiempo() == tiempo);

	  /* Ejecuto cada evento-- de la CEC */

	  do{
	       /* saco una transaccion de la cadena y la hago avanzar
		* por el sistema */
	       CEC.front()->avanzar();
	       CEC.pop_front();
	  }while(CEC.size() > 0);

     }
}

void Sistema::ponerEnFEC(Evento* ev){
     if(ev == NULL)
	  return;
     std::list<Evento*>::iterator it;
     bool salir=false;
     
     /* Pongo el evento en la cadena segun su tiempo */
     for(it=FEC.begin();it!=FEC.end()&&!salir;it++){
	  if(ev->getTiempo() < (*it)->getTiempo()){
	       salir=true;
	       FEC.insert(it, ev);
	  }
     }
}

void Sistema::ponerEnCEC(Transaccion* t){
     if(t == NULL)
	  return;
     //TODO: tener en cuenta las prioridades.
     CEC.push_back(t);
}

double Sistema::getSaveValue(const std::string& nombre){
     return saveValues[nombre];
}

void Sistema::parsear(const std::string& buffer){

     std::map<std::string, bool> keywords;

     const char *words[]={"STORAGE", "TABLE", "QTABLE", "GENERATE", \
			  "VARIABLE", "FUNCTION", "TABULATE", "ADVANCE", \
			  "QUEUE", "SEIZE", "DEPART", "RELEASE", "ENTER",\
			  "LEAVE", "JOIN", "EXAMINE", "TERMINATE", "START",\
			  "TRANSFER", "SPLIT", "GATHER", "LINK", "UNLINK",\
			  "GATE", "TEST", 0};

     for(const char** p=words; *p != NULL; p++){
	  keywords[*p] = true;
     }

     unsigned i=0;
     const char* datos = buffer.c_str();
     char c;
     while(i<buffer.length()){
	  c=datos[i];
	  if(c==' ' || c=='\t' || c=='\n'){ // salteo espacios en blanco
	       //o lineas vacias
	       i++;
	  }
	  else if(c== ';'){ //es un comentario
	       while(datos[++i] != '\n'); //salteo toda la linea
	       i++;
	  }
	  else{ //linea para parsear
	       size_t finLinea = buffer.find_first_of('\n',i);
	       while(i < finLinea){
		    size_t limite = buffer.find_first_of("\n \t;", i);
		    if(buffer[limite] == ';'){ //es un comentario
			 while(datos[++i] != '\n'); //salteo toda la linea
			 i++;
		    }
		    else{
			 std::string nuevo = buffer.substr(i, limite-i);
			 if(nuevo.size()>0)
			      std::cout << nuevo << std::endl;
			 i=limite+1;
		    }
	       }
	  }
     }
}

int main(int argc, char** argv){
     if(argc < 2)
	  return -1;
     std::ifstream archivo(argv[1]);

     std::string datos;
     std::string linea;

     while(std::getline(archivo, linea)){
	  datos+=linea;
	  datos+='\n';
     }

     Sistema::getInstancia().parsear(datos);

}
